﻿using LinkingCloud.API.Common.Helper;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace LinkingCloud.API.Common.RabbitMQ
{
    public class RabbitMQHelper : IRabbitMQHelper
    {
        private readonly ConnectionFactory connectionFactory;
        private readonly RabbitMQSetting rabbitMQSetting;
        private readonly IConnection connection;
        private readonly IModel channel;
        private readonly string exchangeName;
        public RabbitMQHelper(string changeName = "exchange_fanout")
        {
            exchangeName = changeName;
            rabbitMQSetting = Appsettings.GetSectionObject<RabbitMQSetting>("AppSettings:RabbitMQSetting");
            connectionFactory = new ConnectionFactory
            {
                //HostName = rabbitMQSetting.hostName,
                UserName = rabbitMQSetting.userName,
                Password = rabbitMQSetting.password,
                AutomaticRecoveryEnabled = true,//如果connection挂掉是否重新连接
                TopologyRecoveryEnabled = true,//连接恢复后，连接的交换机，队列等是否一同恢复

            };
            string[] str = rabbitMQSetting.hostName.Split(";");
            connection = connectionFactory.CreateConnection(str);
            channel = connection.CreateModel();

        }
        /// <summary>
        /// 批量发送消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queName"></param>
        /// <param name="msgList"></param>
        public void SendData<T>(string queName, List<string> msgList) 
        {
            // 创建一个链接
            using (var connection = connectionFactory.CreateConnection(rabbitMQSetting.hostName.Split(";")))
            {
                // 创建一个通道
                using (var channel = connection.CreateModel())
                {
                    // 在这里还应该声明一个交换机
                    // 声明一个队列
                    channel.QueueDeclare(
                        queue: queName,
                        durable: true,
                        exclusive: false,
                        autoDelete: false,
                        arguments: null);
                    foreach (var msg in msgList)
                    {
                        // 编码一个消息
                        var body = Encoding.UTF8.GetBytes(msg);
                        // 发布一个消息
                        channel.BasicPublish(
                            exchange: string.Empty,
                            routingKey: queName,
                            basicProperties: null,
                            body: body
                            );
                    }
                }
            }
            
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queName"></param>
        /// <param name="msg"></param>
        public void SendData<T>(string queName, string msg)
        {
            // 创建一个链接
            using (var connection = connectionFactory.CreateConnection(rabbitMQSetting.hostName.Split(";")))
            {
                // 创建一个通道
                using (var channel = connection.CreateModel())
                {
                    //定义一个Fanout类型交换机    
                    //channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout, true, false, null);
                    //申明一个队列
                    channel.QueueDeclare(queName, true, false, false, null);
                    //绑定队列，交换机，路由键
                    //channel.QueueBind(queName, exchangeName, queName);

                    var basicProperties = channel.CreateBasicProperties();
                    //1：非持久化 2：可持久化
                    basicProperties.DeliveryMode = 2;
                    var payload = Encoding.UTF8.GetBytes(msg);
                    //var address = new PublicationAddress(ExchangeType.Fanout, exchangeName, queName);
                    //channel.BasicPublish(address, basicProperties, payload);
                    channel.BasicPublish(string.Empty, queName, basicProperties, payload);
                }
            }
            
        }
        /// <summary>
        /// 消费消息
        /// </summary>
        /// <param name="queName"></param>
        /// <param name="received"></param>
        public void Receive(string queName, Action<string> received)
        {
            //事件基本消费者
            EventingBasicConsumer consumer = new EventingBasicConsumer(channel);

            //接收到消息事件
            consumer.Received += (ch, ea) =>
            {
                Thread.Sleep(1000);
                string message = Encoding.UTF8.GetString(ea.Body.ToArray());
                Console.WriteLine(message);
                received(message);
                //确认该消息已被消费
                channel.BasicAck(ea.DeliveryTag, false);
            };
            //启动消费者 设置为手动应答消息
            channel.BasicConsume(queName, false, consumer);
        }
    }

    public class RabbitMQSetting
    {
        public string hostName { get; set; }

        public string userName { get; set; }

        public string password { get; set; }
    }
}
